package cn.edu.tju.elm.controller;

import cn.edu.tju.core.model.User;
import cn.edu.tju.core.model.HttpResult;
import cn.edu.tju.core.model.ResultCodeEnum;
import cn.edu.tju.core.security.repository.UserRepository;
import cn.edu.tju.elm.dto.BusinessDto;
import cn.edu.tju.elm.dto.BusinessCreateDto;
import cn.edu.tju.elm.model.Business;
import cn.edu.tju.elm.service.BusinessService;
import cn.edu.tju.elm.repository.BusinessRepository;
import cn.edu.tju.core.security.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.http.HttpStatus;

import java.util.List;
import java.util.Optional;

import java.time.LocalDateTime;

@RestController
@RequestMapping("/api/businesses")
@Tag(name="管理店铺", description = "提供对店铺的增删改查功能")
public class BusinessController {
    @Autowired
    private UserService userService;

    @Autowired
    BusinessService businessService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BusinessRepository businessRepository;

    @GetMapping("")
    @Operation(summary = "获取所有未被删除的商家列表")
    public HttpResult<List<Business>> getBusinesses() {
        // 1. 调用我们刚刚在 Repository 中定义的新方法
        List<Business> businesses = businessRepository.findAllByDeletedIsFalse();
    
        // 2. 将查询结果用 HttpResult.success 包装后返回
        return HttpResult.success(businesses);
    }
    
    @GetMapping("/user/{userId}")
    @Operation(summary = "获取指定用户拥有的所有商家")
    public HttpResult<List<Business>> getBusinessesByUserId(@PathVariable("userId") Long userId) {
        // 检查用户是否存在
        Optional<User> userOpt = userRepository.findById(userId);
        if (userOpt.isEmpty()) {
            return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "未找到ID为 " + userId + " 的用户");
        }
        
        // 获取该用户关联的所有未删除商家
        List<Business> businesses = businessRepository.findAllByBusinessOwner_IdAndDeletedIsFalse(userId);
        
        // 返回结果
        return HttpResult.success(businesses);
    }

    @PostMapping("")
    @PreAuthorize("hasAnyAuthority('ADMIN', 'BUSINESS')")
    public HttpResult<Business> addBusiness(@RequestBody BusinessCreateDto businessDto){
        // 1. 获取当前操作的管理员信息，用于设置 creator
        // 因为有 @PreAuthorize, 这里可以安全地假设用户已登录且是 ADMIN
        User adminUser = userService.getUserWithAuthorities().get();

        // 2. 根据 DTO 中提供的 ownerId, 查找未来的商家所有者
        User ownerUser = userRepository.findById(businessDto.getBusinessOwner().getId())
                .orElseThrow(() -> new RuntimeException("指定的所有者用户 (Owner) 不存在, ID: " + businessDto.getBusinessOwner().getId()));

        // 3. 创建一个新的 Business 实体
        Business newBusiness = new Business();

        // 4. 从 DTO 中复制信息到新实体
        newBusiness.setBusinessName(businessDto.getBusinessName());
        newBusiness.setBusinessAddress(businessDto.getBusinessAddress());
        newBusiness.setBusinessExplain(businessDto.getBusinessExplain());
        newBusiness.setBusinessImg(businessDto.getBusinessImg());
        newBusiness.setStartPrice(businessDto.getStartPrice());
        newBusiness.setDeliveryPrice(businessDto.getDeliveryPrice());
        newBusiness.setRemarks(businessDto.getRemarks());

        // 5. 设置关键的关联信息和审计字段
        newBusiness.setBusinessOwner(ownerUser); // 设置商家所有者
        newBusiness.setCreateTime(LocalDateTime.now());
        newBusiness.setUpdateTime(LocalDateTime.now());
        newBusiness.setCreator(adminUser.getId());
        newBusiness.setUpdater(adminUser.getId());
        newBusiness.setDeleted(false);

        // 6. 保存到数据库
        Business savedBusiness = businessRepository.save(newBusiness);

        // 7. 返回成功响应
        return HttpResult.success(savedBusiness);
    }

    @GetMapping("/{id}")
    public HttpResult<Business> getBusiness(@PathVariable("id") Long id){
        // 1. 调用 Service 层的方法，获取数据
        Business business = businessService.getBusinessById(id);

        // 2. 判断Service层返回的结果
        if (business != null) {
            // 如果 business 不是 null，说明成功找到了
            // 返回成功状态和找到的 business 数据
            return HttpResult.success(business);
        } else {
            // 如果 business 是 null，说明数据库里没有这个ID的商家
            // 返回失败状态和错误信息
            return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "未找到指定的商家");
        }
    }

    @PutMapping("/{id}")
    @Operation(summary = "更新商家信息")
    @Transactional
    public HttpResult<Business> updateBusiness(@PathVariable("id") Long id, @RequestBody BusinessDto businessDto){
        // 1. 获取当前登录的用户
        Optional<User> currentUserOpt = userService.getUserWithAuthorities();
        if (currentUserOpt.isEmpty()) {
            return HttpResult.failure(ResultCodeEnum.UNAUTHORIZED, "用户未登录");
        }
        User currentUser = currentUserOpt.get();

        // 2. 根据ID从数据库查找需要更新的商家
        Optional<Business> businessOpt = businessRepository.findById(id);
        if (businessOpt.isEmpty()) {
            return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "未找到ID为 " + id + " 的商家");
        }
        Business existingBusiness = businessOpt.get();

        // 3. 权限检查：判断当前用户是否是管理员，或者是否是该商家的所有者
        boolean isAdmin = currentUser.getAuthorities().stream()
                .anyMatch(auth -> "ADMIN".equals(auth.getName()));
        
        // 注意：这里的 getBusinessOwner().getId() 和 currentUser.getId() 类型需要匹配
        boolean isOwner = existingBusiness.getBusinessOwner().getId().equals(currentUser.getId());

        if (!isAdmin && !isOwner) {
            return HttpResult.failure(ResultCodeEnum.FORBIDDEN, "权限不足，无法修改该商家信息");
        }

        // 4. 将 DTO 中的数据更新到从数据库查出来的实体上
        existingBusiness.setBusinessName(businessDto.getBusinessName());
        existingBusiness.setBusinessAddress(businessDto.getBusinessAddress());
        existingBusiness.setBusinessExplain(businessDto.getBusinessExplain());
        existingBusiness.setBusinessImg(businessDto.getBusinessImg());
        existingBusiness.setStartPrice(businessDto.getStartPrice());
        existingBusiness.setDeliveryPrice(businessDto.getDeliveryPrice());
        existingBusiness.setRemarks(businessDto.getRemarks());

        // 5. 更新操作者和操作时间信息
        existingBusiness.setUpdater(currentUser.getId());
        existingBusiness.setUpdateTime(LocalDateTime.now());

        // 6. 保存更新
        Business updatedBusiness = businessRepository.save(existingBusiness);

        // 7. 返回成功响应
        return HttpResult.success(updatedBusiness);
    }

    @PatchMapping("/{id}")
    @Operation(summary = "局部更新商家信息", description = "只更新请求体中提供的字段，未提供的字段保持不变")
    @Transactional
    public HttpResult<Business> patchBusiness(@PathVariable("id") Long id, @RequestBody BusinessDto businessDto) {
        // 1. 获取当前登录的用户信息（与PUT/DELETE逻辑相同）
        User currentUser = userService.getUserWithAuthorities()
                .orElseThrow(() -> new AccessDeniedException("用户未登录"));
    
        // 2. 查找商家是否存在（与PUT/DELETE逻辑相同）
        Business existingBusiness = businessRepository.findById(id)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "未找到ID为 " + id + " 的商家"));
    
        // 3. 权限检查（与PUT/DELETE逻辑相同）
        boolean isAdmin = currentUser.getAuthorities().stream()
                .anyMatch(auth -> "ADMIN".equals(auth.getName()));
        boolean isOwner = existingBusiness.getBusinessOwner().getId().equals(currentUser.getId());
    
        if (!isAdmin && !isOwner) {
            return HttpResult.failure(ResultCodeEnum.FORBIDDEN, "权限不足，无法修改该商家信息");
        }
    
        // 4. --- PATCH 核心逻辑：逐个检查并更新字段 ---
        boolean isUpdated = false; // 用于标记是否真的有字段被更新了
    
        if (businessDto.getBusinessName() != null) {
            existingBusiness.setBusinessName(businessDto.getBusinessName());
            isUpdated = true;
        }
        if (businessDto.getBusinessAddress() != null) {
            existingBusiness.setBusinessAddress(businessDto.getBusinessAddress());
            isUpdated = true;
        }
        if (businessDto.getBusinessExplain() != null) {
            existingBusiness.setBusinessExplain(businessDto.getBusinessExplain());
            isUpdated = true;
        }
        if (businessDto.getBusinessImg() != null) {
            existingBusiness.setBusinessImg(businessDto.getBusinessImg());
            isUpdated = true;
        }
        if (businessDto.getStartPrice() != null) {
            existingBusiness.setStartPrice(businessDto.getStartPrice());
            isUpdated = true;
        }
        if (businessDto.getDeliveryPrice() != null) {
            existingBusiness.setDeliveryPrice(businessDto.getDeliveryPrice());
            isUpdated = true;
        }
        if (businessDto.getRemarks() != null) {
            existingBusiness.setRemarks(businessDto.getRemarks());
            isUpdated = true;
        }
    
        // 5. 如果有任何字段被更新了，则更新审计信息并保存
        if (isUpdated) {
            existingBusiness.setUpdater(currentUser.getId());
            existingBusiness.setUpdateTime(LocalDateTime.now());
            Business updatedBusiness = businessRepository.save(existingBusiness);
            return HttpResult.success(updatedBusiness);
        }
    
        // 6. 如果请求体为空或未提供任何可更新的字段，直接返回当前数据
        return HttpResult.success(existingBusiness);
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除一个商家（软删除）")
    @Transactional
    public HttpResult<Object> deleteBusiness(@PathVariable("id") Long id){
        // 1. 获取当前登录的用户
        User currentUser = userService.getUserWithAuthorities()
                .orElseThrow(() -> new AccessDeniedException("用户未登录，无法执行删除操作"));

        // 2. 查找商家是否存在
        Business businessToDelete = businessRepository.findById(id)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "未找到ID为 " + id + " 的商家"));

        // 3. 权限检查：必须是管理员或者是商家所有者本人
        boolean isAdmin = currentUser.getAuthorities().stream()
                .anyMatch(auth -> "ADMIN".equals(auth.getName()));
        
        // 注意：这里的 getBusinessOwner() 不能为空
        if (businessToDelete.getBusinessOwner() == null) {
            return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "商家数据异常，缺少所有者信息");
        }
        boolean isOwner = businessToDelete.getBusinessOwner().getId().equals(currentUser.getId());

        if (!isAdmin && !isOwner) {
            return HttpResult.failure(ResultCodeEnum.FORBIDDEN, "权限不足，无法删除该商家");
        }
        
        // 4. 执行软删除操作
        businessToDelete.setDeleted(true);
        businessToDelete.setUpdater(currentUser.getId());
        businessToDelete.setUpdateTime(LocalDateTime.now());
        
        // 5. 保存更改到数据库
        businessRepository.save(businessToDelete);
        
        // 6. 返回成功信息 (删除成功后一般不需要返回被删除的对象，返回null即可)
        return HttpResult.success(null);
    }
}
